home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Speccy ClassiX 1998
/
Speccy ClassiX 98.iso
/
amiga_system
/
the_aminet
/
dev
/
gcc
/
ixemulsrc.lha
/
ixemul-41.4
/
library
/
_main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-05-20
|
7KB
|
271 lines
/*
* This file is part of ixemul.library for the Amiga.
* Copyright (C) 1991, 1992 Markus M. Wild
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* _main.c,v 1.1.1.1 1994/04/04 04:30:43 amiga Exp
*
* _main.c,v
* Revision 1.1.1.1 1994/04/04 04:30:43 amiga
* Initial CVS check in.
*
* Revision 1.3 1992/08/09 20:41:54 amiga
* change to use 2.x header files by default
* add option to ignore global environment (ix.ix_ignore_global_env).
*
* Revision 1.2 1992/07/04 19:10:06 mwild
* add call to ix_install_sigwinch().
*
* Revision 1.1 1992/05/17 21:01:29 mwild
* Initial revision
*
*
*/
#define KERNEL
#include "ixemul.h"
#include "kprintf.h"
#include <dos/var.h>
#include <workbench/startup.h>
#include <dirent.h>
extern struct ExecBase *SysBase;
static char **
__get_environ (void)
{
static char *endmarker = 0;
char **env = &endmarker;
DIR *dp;
struct dirent *de;
int num_env, num_local = 0;
char **cp;
/* 2.0 local environment overrides 1.3 global environment */
struct Process *me = (struct Process *) FindTask (0);
struct LocalVar *lv, *nlv;
/* count total number of local variables (skip aliases) */
for (num_local = 0,
lv = (struct LocalVar *) me->pr_LocalVars.mlh_Head;
nlv = (struct LocalVar *) lv->lv_Node.ln_Succ;
lv = nlv)
if (lv->lv_Node.ln_Type == LV_VAR)
num_local ++;
if (cp = (char **) syscall (SYS_malloc, (num_local + 1) * 4))
{
env = cp;
for (lv = (struct LocalVar *) me->pr_LocalVars.mlh_Head;
nlv = (struct LocalVar *) lv->lv_Node.ln_Succ;
lv = nlv)
{
/* I'm not interested in aliases, really not ;-)) */
if (lv->lv_Node.ln_Type != LV_VAR)
continue;
/* NAME=CONTENTS\0 */
*cp = (char *) syscall (SYS_malloc, (strlen (lv->lv_Node.ln_Name)
+ 1 + lv->lv_Len + 1));
if (*cp)
sprintf (*cp, "%s=%*.*s", lv->lv_Node.ln_Name,
lv->lv_Len, lv->lv_Len, lv->lv_Value);
else
break;
cp ++;
}
*cp = 0;
}
else
num_local = 0;
if (ix.ix_ignore_global_env)
return env;
/* now go for global variables */
if (dp = (DIR *) syscall (SYS_opendir, "ENV:"))
{
/* first count how many entries we have */
for (num_env = 0; readdir (dp); num_env++) ;
/* skip . and .. */
syscall (SYS_rewinddir, dp);
if ((de = (struct dirent *) syscall (SYS_readdir, dp))
&& de->d_namlen == 1 && de->d_name[0] == '.' && --num_env &&
(de = (struct dirent *) syscall (SYS_readdir, dp))
&& de->d_namlen == 2 && de->d_name[0] == '.' && de->d_name[1] == '.')
{
num_env --;
de = (struct dirent *) syscall (SYS_readdir, dp);
}
if (num_local)
{
/* only (!) in this case is `env' allocated and not static */
char **tmp = (char **) syscall (SYS_realloc,
env, (num_local + num_env + 1) * 4);
if (tmp)
{
cp = tmp + (cp - env);
env = tmp;
}
else
/* out of memory !!! */
return &endmarker;
}
else
{
if (cp = (char **) syscall (SYS_malloc, (num_env + 1) * 4))
env = cp;
else
/* out of memory !!! */
return &endmarker;
}
for (;de; de = (struct dirent *) syscall (SYS_readdir, dp))
{
struct stat stb;
int len = 0;
char envfile[MAXPATHLEN];
/* If this variable already exists locally, skip it */
if (FindVar (de->d_name, GVF_LOCAL_ONLY))
continue;
/* Don't include variables with funny names, and don't include
multiline variables either, they totally confuse ksh.. */
if (index (de->d_name, '.'))
continue;
sprintf (envfile, "ENV:%s", de->d_name);
if (stat (envfile, &stb) == 0)
{
len = stb.st_size;
/* skip directories... shudder */
if (! S_ISREG (stb.st_mode))
continue;
}
/* NAME=CONTENTS\0 */
*cp = (char *) syscall (SYS_malloc,
de->d_namlen + 1 + len + 1);
if (*cp)
{
int written = sprintf (*cp, "%s=", de->d_name);
int fd;
if (len)
{
fd = open (envfile, 0);
if (fd >= 0)
{
written += read (fd, *cp + written, len);
(*cp)[written] = 0;
if ((*cp)[--written] == '\n')
(*cp)[written] = 0;
close (fd);
}
/* now filter out those multiliners (that is,
variables containing \n, you can have variables
as long as want, but don't use \n... */
if (index (*cp, '\n'))
{
syscall (SYS_free, *cp);
continue;
}
}
}
else
break;
cp ++;
}
*cp = 0;
syscall (SYS_closedir, dp);
return env;
}
else
/* `panic!', no ENV: logical ! */
return &endmarker;
}
/* smells abit kludgy I know.. but can live with quite few variables in
* the user area
*/
int
_main (union { char *_aline; struct WBStartup *_wb_msg; } a1,
union { int _alen; char *_def_window; } a2,
int (* main(int, char **, char **)))
#define aline a1._aline
#define alen a2._alen
#define wb_msg a1._wb_msg
#define def_window a2._def_window
{
struct Process *me = (struct Process *)SysBase->ThisTask;
int exit_val;
char **argv, **env;
int argc;
KPRINTF (("entered __main()\n"));
if (! me->pr_CLI)
{
/* Workbench programs expect to have their CD where the executed
* program lives. */
if (wb_msg->sm_ArgList)
{
CurrentDir (wb_msg->sm_ArgList->wa_Lock);
syscall (SYS__wb_parse, me, wb_msg, def_window);
}
/* argc==0: this means, that argv is really a WBenchMsg, not a vector */
argc = 0;
argv = (char **) wb_msg;
}
else
{
/* if we were started from the CLI, alen & aline are valid and
* should now be split into arguments. This is done by the
* function "_cli_parse()", which does wildcard expansion if not
* disabled (see cli_parse.c). */
_cli_parse (me, alen, aline, &argc, &argv);
}
env = __get_environ ();
/* this is not really the right thing to do, the user should call
ix_get_vars2 () to initialize environ to the address of the variable
in the calling program. However, this setting guarantees that
the user area entry is valid for getenv() calls. */
u.u_environ = &env;
ix_install_sigwinch ();
syscall (SYS_exit, main (argc, argv, env));
}